package org.dflish.mybatis.encrypt.rule;

import cn.hutool.crypto.SecureUtil;
import cn.hutool.crypto.symmetric.AES;
import org.apache.commons.codec.digest.DigestUtils;
import org.dflish.mybatis.encrypt.properties.EnCryptProperties;
import org.dflish.mybatis.encrypt.properties.EncryptColumnRuleConfiguration;
import org.dflish.mybatis.encrypt.properties.EncryptTableRuleConfiguration;
import org.dflish.mybatis.encrypt.util.DesensitizedExecutor;
import org.dflish.mybatis.encrypt.util.DesensitizedType;

import java.util.Arrays;
import java.util.Map;
import java.util.Optional;

/**
 * @author liangwx
 */
public class EncryptRule {

    private final EnCryptProperties properties;

    private final Map<String, EncryptTableRuleConfiguration> tables;

    private final String key;

    private final AES aes;


    public EncryptRule(EnCryptProperties properties) {
        this.properties = properties;
        this.tables = properties.getTables();
        this.key = properties.getKey();

        final byte[] bytes = Arrays.copyOf(DigestUtils.sha1(key), 16);
        aes = SecureUtil.aes(bytes);
    }

    public Optional<EncryptColumnRuleConfiguration> getEncryptColumnRuleConfiguration(String tableName, String columnName){

        if (!tables.containsKey(tableName)){
            return Optional.empty();
        }

        final EncryptTableRuleConfiguration encryptTableRuleConfiguration = tables.get(tableName);

        final Map<String, EncryptColumnRuleConfiguration> columns = encryptTableRuleConfiguration.getColumns();

        if (!columns.containsKey(columnName.toLowerCase())){
            return Optional.empty();
        }

        return Optional.of(columns.get(columnName.toLowerCase()));
    }

    public boolean containsColumn(String tableName, String columnName){

        return getEncryptColumnRuleConfiguration(tableName, columnName).isPresent();
    }

    public Object getEncryptedValues(String tableName, String columnName, final Object originalValues) {

        if (!(originalValues instanceof String)){
            return originalValues;
        }

        final Optional<EncryptColumnRuleConfiguration> encryptColumnRuleConfiguration = getEncryptColumnRuleConfiguration(tableName, columnName);

        if (!encryptColumnRuleConfiguration.isPresent()){
            return originalValues;
        }

        final EncryptColumnRuleConfiguration configuration = encryptColumnRuleConfiguration.get();

        if (configuration.getEncryptor()){
            return aes.encryptBase64((String) originalValues);
        }

        if (configuration.getDesensitized()){
            return DesensitizedExecutor.desensitized(DesensitizedType.MOBILE_PHONE, (String) originalValues);
        }

        return originalValues;
    }


}
